home *** CD-ROM | disk | FTP | other *** search
- /*----------------------------------------------------------------------------
-
- tcplow.c
-
- This module all the low-level calls to MacTCP.
- Copyright © Mikhail Fridberg, 1994
- Portions copyright © 1990, Apple Computer.
- Portions copyright © 1993, Northwestern University.
-
- ----------------------------------------------------------------------------*/
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <errno.h>
- #include <time.h>
- #include <stddef.h>
- #include <string.h>
- #include "MacSocket.h"
- #include <MacTCPCommonTypes.h>
- #include <TCPPB.h>
- #include <AddressXlation.h>
- #include <GetMyIPAddr.h>
- #include <MiscIPPB.h>
- #include "tcplow.h"
-
-
- Boolean gCancel = false; /* flag set when user cancels an action */
- short gRefNum;
-
-
-
- /* This is the completion routine used for name-resolver calls.
- It sets the userDataPtr flag to indicate the call has completed.
- */
-
- pascal void DNRResultProc(struct hostInfo *hInfoPtr,char *userDataPtr)
- {
- #pragma unused (hInfoPtr)
-
- *userDataPtr = 0xff; /* setting the use data to non-zero means we're done */
- }
-
-
- short GetTCPRefNum (void)
- {
- return gRefNum;
- }
-
-
- static void InitBlock (TCPiopb *pBlock)
- {
- memset(pBlock, 0L, sizeof(TCPiopb));
- pBlock->ioResult = 1;
- pBlock->ioCRefNum = GetTCPRefNum();
- }
-
-
- static OSErr NewBlock (TCPiopb **pBlock)
- {
- *pBlock = (TCPiopb *)malloc(sizeof(TCPiopb));
- if (MemError() != noErr) {
- printf ("Couldn not allocate memory, error = %d\n", MemError());
- return MemError();
- }
- (*pBlock)->ioCompletion = 0L;
- (*pBlock)->ioCRefNum = gRefNum;
- return noErr;
- }
-
-
- /* Opens the MacTCP driver.
- This routine must be called prior to any of the below functions. */
-
- OSErr OpenTCPDriver (void)
- {
- OSErr err;
-
- err = OpenDriver("\p.IPP", &gRefNum);
- return(err);
- }
-
-
- /* Creates a new TCP stream in preparation for initiating a connection.
- A buffer must be provided for storing incoming data waiting to be processed */
-
- OSErr LowTCPCreateStream (StreamPtr *streamPtr, Ptr connectionBuffer,
- unsigned long connBufferLen, TCPNotifyProc notifPtr)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPCreate;
- pBlock->ioResult = 1;
- pBlock->csParam.create.rcvBuff = connectionBuffer;
- pBlock->csParam.create.rcvBuffLen = connBufferLen;
- pBlock->csParam.create.notifyProc = notifPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
-
- *streamPtr = pBlock->tcpStream;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
-
- }
-
-
- /* If TCPWaitForConnection is called asynchronously, this command retrieves the
- result of the call. It should be called when the above command completes. */
-
- OSErr LowFinishTCPWaitForConn (TCPiopb *pBlock, ip_addr *remoteHost,
- tcp_port *remotePort, ip_addr *localHost, tcp_port *localPort)
- {
- OSErr err;
-
- *remoteHost = pBlock->csParam.open.remoteHost;
- *remotePort = pBlock->csParam.open.remotePort;
- *localHost = pBlock->csParam.open.localHost;
- *localPort = pBlock->csParam.open.localPort;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* Waits for a connection to be opened on a specified port from a specified address.
- It completes when a connection is made, or a timeout value is reached. This call
- may be made asynchronously. */
-
- OSErr LowTCPWaitForConnection (StreamPtr streamPtr, byte timeout,
- ip_addr *remoteHost, tcp_port *remotePort, ip_addr *localHost,
- tcp_port *localPort, Boolean async, TCPiopb **returnBlock)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPPassiveOpen;
- pBlock->ioResult = 1;
- pBlock->ioCompletion = nil;
- pBlock->tcpStream = streamPtr;
- pBlock->csParam.open.ulpTimeoutValue = timeout;
- pBlock->csParam.open.ulpTimeoutAction = 1;
- pBlock->csParam.open.validityFlags = 0xC0;
- pBlock->csParam.open.commandTimeoutValue = timeout;
- pBlock->csParam.open.remoteHost = *remoteHost;
- pBlock->csParam.open.remotePort = *remotePort;
- pBlock->csParam.open.localPort = *localPort;
- pBlock->csParam.open.tosFlags = 0;
- pBlock->csParam.open.precedence = 0;
- pBlock->csParam.open.dontFrag = 0;
- pBlock->csParam.open.timeToLive = 0;
- pBlock->csParam.open.security = 0;
- pBlock->csParam.open.optionCnt = 0;
- PBControl((ParmBlkPtr)pBlock,true);
- if (!async) {
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- err = gCancel ? -1 : pBlock->ioResult;
- if (gCancel) LowTCPAbort(streamPtr);
- LowFinishTCPWaitForConn(pBlock,remoteHost,remotePort,localHost,localPort);
- return err;
- }
-
- *returnBlock = pBlock;
- return noErr;
- }
-
-
- /* Attempts to initiate a connection with a host specified by host and port. */
-
- OSErr LowTCPOpenConnection (StreamPtr streamPtr, Byte timeout,
- ip_addr remoteHost, tcp_port remotePort, ip_addr *localHost,
- tcp_port *localPort)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPActiveOpen;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- pBlock->csParam.open.ulpTimeoutValue = timeout;
- pBlock->csParam.open.ulpTimeoutAction = 1;
- pBlock->csParam.open.validityFlags = 0xC0;
- pBlock->csParam.open.commandTimeoutValue = timeout;
- pBlock->csParam.open.remoteHost = remoteHost;
- pBlock->csParam.open.remotePort = remotePort;
- pBlock->csParam.open.localPort = *localPort;
- pBlock->csParam.open.tosFlags = 0;
- pBlock->csParam.open.precedence = 0;
- pBlock->csParam.open.dontFrag = 0;
- pBlock->csParam.open.timeToLive = 0;
- pBlock->csParam.open.security = 0;
- pBlock->csParam.open.optionCnt = 0;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- *localHost = pBlock->csParam.open.localHost;
- *localPort = pBlock->csParam.open.localPort;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* This routine should be called when a TCPSendData call completes. It returns the
- error code generated upon completion of the CallTCPSend. */
-
- OSErr LowFinishTCPSend (TCPiopb *pBlock)
- {
- OSErr err;
-
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* Sends data through an open connection stream. Note that the connection must be
- open before any data is sent. This call may be made asynchronously. */
-
- OSErr LowTCPSendData (StreamPtr streamPtr, byte timeout, Boolean push,
- Boolean urgent, Ptr wdsPtr, Boolean async, TCPiopb **returnBlock)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPSend;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- pBlock->ioCompletion = nil;
- pBlock->csParam.send.ulpTimeoutValue = timeout;
- pBlock->csParam.send.ulpTimeoutAction = 1;
- pBlock->csParam.send.validityFlags = 0xC0;
- pBlock->csParam.send.pushFlag = push;
- pBlock->csParam.send.urgentFlag = urgent;
- pBlock->csParam.send.wdsPtr = wdsPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- if (!async) {
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- err = gCancel ? -1 : pBlock->ioResult;
- if (gCancel) LowTCPAbort(streamPtr);
- LowFinishTCPSend(pBlock);
- return err;
- }
-
- *returnBlock = pBlock;
- return noErr;
- }
-
-
- OSErr LowFinishTCPNoCopyRcv (TCPiopb *pBlock, Boolean *urgent, Boolean *mark)
- {
- OSErr err;
-
- *urgent = pBlock->csParam.receive.urgentFlag;
- *mark = pBlock->csParam.receive.markFlag;
-
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- OSErr LowTCPNoCopyRcv (StreamPtr streamPtr, byte timeout, Boolean *urgent,
- Boolean *mark, Ptr rdsPtr, short numEntry, Boolean async,
- TCPiopb **returnBlock)
- {
- OSErr err = noErr;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPNoCopyRcv;
- pBlock->tcpStream = streamPtr;
- pBlock->ioResult = 1;
- pBlock->ioCompletion = nil;
- pBlock->csParam.receive.commandTimeoutValue = timeout;
- pBlock->csParam.receive.rdsPtr = rdsPtr;
- pBlock->csParam.receive.rdsLength = numEntry;
- PBControl((ParmBlkPtr)pBlock,true);
- if (!async) {
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- err = gCancel ? -1 : pBlock->ioResult;
- if (gCancel) LowTCPAbort(streamPtr);
- LowFinishTCPNoCopyRcv(pBlock,urgent,mark);
- return err;
- }
-
- *returnBlock = pBlock;
- return noErr;
- }
-
-
- OSErr LowTCPBfrReturn (StreamPtr streamPtr, Ptr rdsPtr)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPRcvBfrReturn;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- pBlock->csParam.receive.rdsPtr = rdsPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* If the above is called asynchronously, this routine returns the data that was
- received from the remote host. */
-
- OSErr LowFinishTCPRecv (TCPiopb *pBlock, Boolean *urgent, Boolean *mark,
- unsigned short *rcvLen)
- {
- OSErr err;
-
- *rcvLen = pBlock->csParam.receive.rcvBuffLen;
- *urgent = pBlock->csParam.receive.urgentFlag;
- *mark = pBlock->csParam.receive.markFlag;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* Attempts to pull data out of the incoming stream for a connection. If data is
- not present, the routine waits a specified amout of time before returning with
- a timeout error. This call may be made asynchronously. */
-
- OSErr LowTCPRecvData (StreamPtr streamPtr, byte timeout, Boolean *urgent,
- Boolean *mark, Ptr rcvBuff, unsigned short *rcvLen, Boolean async,
- TCPiopb **returnBlock)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPRcv;
- pBlock->ioResult = 1;
- pBlock->ioCompletion = nil;
- pBlock->tcpStream = streamPtr;
- pBlock->csParam.receive.commandTimeoutValue = timeout;
- pBlock->csParam.receive.rcvBuff = rcvBuff;
- pBlock->csParam.receive.rcvBuffLen = *rcvLen;
- PBControl((ParmBlkPtr)pBlock,true);
- if (!async) {
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- err = gCancel ? -1 : pBlock->ioResult;
- if (gCancel) LowTCPAbort(streamPtr);
- LowFinishTCPRecv(pBlock,urgent,mark,rcvLen);
- return err;
- }
-
-
- *returnBlock = pBlock;
- return noErr;
- }
-
-
- /* Gracefully closes a connection with a remote host. This is not always possible,
- and the programmer might have to resort to CallTCPAbort, described next. */
-
- OSErr LowTCPClose (StreamPtr streamPtr, byte timeout)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPClose;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- pBlock->csParam.close.ulpTimeoutValue = timeout;
- pBlock->csParam.close.validityFlags = 0xC0;
- pBlock->csParam.close.ulpTimeoutAction = 1;
- PBControl((ParmBlkPtr)&pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- err = gCancel ? -1 : pBlock->ioResult;
- if (gCancel) LowTCPAbort(streamPtr);
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
-
- return err;
- }
-
-
- /* Should be called if a CallTCPClose fails to close a connection properly.
- This call should not normally be used to terminate connections. */
-
- OSErr LowTCPAbort (StreamPtr streamPtr)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPAbort;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
- OSErr LowTCPStatus (StreamPtr streamPtr, TCPStatusPB *theStatus)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPStatus;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- theStatus = &(pBlock->csParam.status);
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
- /* Deallocates internal buffers used to hold connection data. This should be
- called after a connection has been closed. */
-
- OSErr LowTCPRelease (StreamPtr streamPtr, Ptr *recvPtr, unsigned long *recvLen)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPRelease;
- pBlock->ioResult = 1;
- pBlock->tcpStream = streamPtr;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- *recvPtr = pBlock->csParam.create.rcvBuff;
- *recvLen = pBlock->csParam.create.rcvBuffLen;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
- OSErr LowTCPGlobalInfo (Ptr *tcpParam, Ptr *tcpStat)
- {
- OSErr err;
- TCPiopb *pBlock = 0;
-
- if ((err = NewBlock(&pBlock)) != noErr)
- return err;
-
- pBlock->csCode = TCPGlobalInfo;
- pBlock->ioResult = 1;
- PBControl((ParmBlkPtr)pBlock,true);
- while (pBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- *tcpParam = (Ptr) pBlock->csParam.globalInfo.tcpParamPtr;
- *tcpStat = (Ptr) pBlock->csParam.globalInfo.tcpStatsPtr;
- err = pBlock->ioResult;
- free((Ptr)pBlock);
- if (MemError() != noErr) {
- printf ("Couldn not free memory, error = %d\n", MemError());
- }
- return err;
- }
-
-
-
- /* LowIPNameToAddr invokes the domain name system to translate a domain name
- into an IP address. */
-
- OSErr LowIPNameToAddr (char *name, unsigned long *addr)
- {
- struct hostInfo hInfo;
- OSErr err;
- Boolean done=false;
-
- if ((err = OpenResolver(nil)) != noErr) return err;
- err = StrToAddr(name, &hInfo, DNRResultProc, (char*)&done);
- if (err == cacheFault) {
- while (!done) GiveTime();
- err = hInfo.rtnCode;
- }
- CloseResolver();
- *addr = hInfo.addr[0];
- return gCancel ? -1 : err;
- }
-
-
- /* LowIPAddrToName invokes the domain name system to translate an IP address
- into a domain name. */
-
- OSErr LowIPAddrToName (unsigned long addr, char *name)
- {
- struct hostInfo hInfo;
- OSErr err;
- Boolean done=false;
-
- if ((err = OpenResolver(nil)) != noErr) return err;
- err = AddrToName(addr, &hInfo, DNRResultProc, (char*)&done);
- if (err == cacheFault) {
- while (!done) GiveTime();
- err = hInfo.rtnCode;
- }
- CloseResolver();
- hInfo.cname[254] = 0;
- strcpy(name,hInfo.cname);
- return gCancel ? -1 : err;
- }
-
-
- /* LowGetMyIPAddr returns the IP address of this Mac. */
-
- OSErr LowGetMyIPAddr (unsigned long *addr)
- {
- struct GetAddrParamBlock IPBlock;
-
- memset(&IPBlock, 0, sizeof(IPBlock));
- IPBlock.ioResult = 1;
- IPBlock.csCode = ipctlGetAddr;
- IPBlock.ioCRefNum = gRefNum;
- PBControl((ParmBlkPtr)&IPBlock,true);
- while (IPBlock.ioResult > 0) GiveTime();
-
-
- *addr = IPBlock.ourAddress;
-
-
- return gCancel ? -1 : IPBlock.ioResult;
- }
-
-
- /* LowGetMyIPAddrStr returns the IP address of this Mac as a dotted decimal
- string. */
-
- OSErr LowGetMyIPAddrStr (char *addrStr)
- {
- unsigned long addr;
- OSErr err;
- static char theAddrStr[16];
- static Boolean gotIt=false;
-
- if (!gotIt) {
- if ((err = LowGetMyIPAddr(&addr)) != noErr) return err;
- if ((err = OpenResolver(nil)) != noErr) return err;
- err = AddrToStr(addr,theAddrStr);
- CloseResolver();
- if (err != noErr) return err;
- gotIt = true;
- }
- strcpy(addrStr,theAddrStr);
- return noErr;
- }
- OSErr GetMyIP(ip_addr *ipnum)
- {
- struct GetAddrParamBlock *IPBlock = 0;
- OSErr err;
-
- IPBlock = (struct GetAddrParamBlock *)malloc(sizeof(struct GetAddrParamBlock));
- if (MemError() != noErr) {
- printf ("Couldn not allocate memory, error = %d\n", MemError());
- return MemError();
- }
- IPBlock->ioResult = 1;
- IPBlock->csCode = ipctlGetAddr;
- IPBlock->ioCompletion = nil;
- IPBlock->ioCRefNum = gRefNum;
- PBControl((ParmBlkPtr)IPBlock,true);
- while (IPBlock->ioResult > 0 && GiveTime())
- ;
- if (gCancel)
- return -1;
- *ipnum = IPBlock->ourAddress;
- err = IPBlock->ioResult;
- free((Ptr)IPBlock);
- if (MemError() != noErr) {
- printf ("Couldn not allocate memory, error = %d\n", MemError());
- }
- return err;
- }
-
- /* RecvData() waits for data to be received on a connection stream. When data
- arrives, it is copied into the data buffer and the call terminates. */
-
- OSErr RecvData (unsigned long stream, Ptr data, unsigned short *length,
- Boolean retry)
- {
- Boolean urgent,mark;
- OSErr err;
- unsigned short recvLength;
-
- do {
- recvLength = *length;
- err = LowTCPRecvData(stream,1,&urgent,&mark,data,&recvLength,false,nil);
- }
- while (retry && err==commandTimeout);
- *length = recvLength;
- if (err == noErr) *(data+*length) = 0;
- return err;
- }
-
- /* SendData() sends data along a connection stream to a remote host. */
-
- OSErr SendData (unsigned long stream, Ptr data, unsigned short length)
- {
- struct wdsEntry myWDS[2]; /* global write data structure */
-
- myWDS[0].length = length;
- myWDS[0].ptr = data;
- myWDS[1].length = 0;
- myWDS[1].ptr = nil;
- return LowTCPSendData(stream,120,false,false,(Ptr) myWDS,false,nil);
- }
-
- /*************************************************************************************/
- /* This are utilities routines */
- /*************************************************************************************/
-
-
-
- /* GiveTime is called whenever the application is waiting for a slow
- process to complete. The routine calls SpinCursor and WaitNextEvent
- to give time to currently running background applications.
- */
-
- Boolean GiveTime (void)
- {
- EventRecord ev;
- Boolean gotEvt;
-
-
- SpinCursor(1);
- gotEvt = WaitNextEvent(everyEvent,&ev,0x01,nil);
- return !gCancel;
- }
-
-
- /* pstrcpy copies Pascal format strings.
- */
-
- void pstrcpy (StringPtr to, StringPtr from)
- {
- BlockMove(from, to, *from+1);
- }
-
-
-
-
- /* The InitCursorCtl, SpinCursor functions
- are missing in Think, so we include them here */
-
- Handle gAcur = nil;
-
- pascal void InitCursorCtl (Handle id)
- {
- short NoFrames, i, CursId;
- CursHandle TheCursHndl;
-
- if (id == nil) {
- gAcur = (Handle) GetResource('acur',0);
- if(gAcur == nil) return;
- HLock(gAcur);
- NoFrames = ((short *)(*gAcur))[0];
- for(i = 0; i < NoFrames; i++) {
- CursId = ((short *)(*gAcur))[(2*i)+2];
- TheCursHndl = GetCursor(CursId);
- ((CursHandle *)(*gAcur))[i+1] = TheCursHndl;
- HLock((Handle)TheCursHndl);
- }
- } else {
- gAcur = id;
- HLock(gAcur);
- NoFrames = ((short *)(*gAcur))[0];
- for(i = 0; i < NoFrames; i++) {
- CursId = ((short *)(*gAcur))[(2*i)+2];
- TheCursHndl = GetCursor(CursId);
- ((CursHandle *)(*gAcur))[i+1] = TheCursHndl;
- HLock((Handle)TheCursHndl);
- }
- }
- ((short *)(*gAcur))[1] = 0;
- DetachResource(gAcur);
- }
-
-
- pascal void SpinCursor (short num)
- {
- short NoFrames, CurrentFrame, CurrentCounter;
- Cursor CurrentCursor;
-
- if (gAcur == nil) InitCursorCtl(nil);
- NoFrames = ((short *)(*gAcur))[0];
- CurrentCounter = ((((short *)(*gAcur))[1] + num) % (NoFrames * 32));
- ((short *)(*gAcur))[1] = CurrentCounter;
- CurrentFrame = CurrentCounter / 32;
- CurrentCursor = **(((CursHandle *)(*gAcur))[CurrentFrame+1]);
- SetCursor(&CurrentCursor);
- }
-
-
-